/*:
 * @target MZ
 * @plugindesc Live2Dモデルの特定部位に円形モザイクをかける（追従・スイッチ制御対応）
 * @author ChatGPT
 * 
 * @help Live2DMosaicFilter.js
 *
 * Live2DInterfaceMZ.js にて表示中のLive2Dモデルに対し、
 * 特定のアートメッシュ（例："Part_Mosaic"）に追従する円形モザイクを表示します。
 * モザイクの有効／無効はツクール内のスイッチで制御可能です。
 *
 * 使用方法:
 *   - 本プラグインを導入
 *   - 以下のスクリプトをコモンイベントなどで実行:
 *
 * Live2DMosaicFilter.add({
 *     modelName: "chisa_01",
 *     drawableId: "Part_Mosaic",
 *     radius: 30,
 *     pixelSize: 11,
 *     switchId: 10
 * });
 */

var Live2DMosaicFilter = (() => {
    const mosaicEntries = [];

    const plugin = {
        add({modelName, drawableId, radius = 30, pixelSize = 11, switchId = 0}) {
            mosaicEntries.push({ modelName, drawableId, radius, pixelSize, switchId, sprite: null, mask: null });
        },

        update() {
            for (const entry of mosaicEntries) {
                const modelSprite = SceneManager._scene.children.find(child =>
                    child._live2dModel && child._live2dModel.modelID === entry.modelName);
                if (!modelSprite || !$gameSwitches.value(entry.switchId)) {
                    if (entry.sprite) entry.sprite.visible = false;
                    continue;
                }

                const internal = modelSprite._live2dModel.internalModel;
                const drawables = internal.drawables;
                const idx = drawables.ids.indexOf(entry.drawableId);
                if (idx < 0) continue;

                const verts = drawables.vertexPositions[idx];
                let x = 0, y = 0, len = verts.length / 2;
                for (let i = 0; i < verts.length; i += 2) {
                    x += verts[i];
                    y += verts[i + 1];
                }
                x /= len;
                y /= len;

                const pos = modelSprite._live2dModel.toGlobal(new PIXI.Point(x, y));

                if (!entry.sprite) {
                    const r = entry.radius;
                    const g = new PIXI.Graphics();
                    g.beginFill(0xffffff);
                    g.drawCircle(0, 0, r);
                    g.endFill();

                    const rt = PIXI.RenderTexture.create({width: r*2, height: r*2});
                    const s = new PIXI.Sprite(rt);
                    s.filters = [new PIXI.filters.PixelateFilter(entry.pixelSize)];
                    s.mask = g;
                    s.addChild(g);
                    SceneManager._scene.addChild(s);
                    entry.sprite = s;
                    entry.mask = g;
                }

                entry.sprite.visible = true;
                entry.sprite.x = pos.x - entry.radius;
                entry.sprite.y = pos.y - entry.radius;
                entry.mask.x = entry.radius;
                entry.mask.y = entry.radius;

                // 再描画（Live2DモデルをRenderTextureに描き写す等が必要）
                const r = entry.radius;
                const rt = entry.sprite.texture;
                SceneManager._scene.app.renderer.render(modelSprite, rt, false, new PIXI.Rectangle(pos.x - r, pos.y - r, r * 2, r * 2));
            }
        }
    };

    const _Scene_Map_update = Scene_Map.prototype.update;
    Scene_Map.prototype.update = function() {
        _Scene_Map_update.call(this);
        plugin.update();
    };

    return plugin;
})();
